import 'dart:collection';
import 'dart:ui';

import 'package:flutter/cupertino.dart';

class FpsTextComponent extends StatefulWidget {
  const FpsTextComponent({super.key});

  @override
  State<StatefulWidget> createState() => _FpsTextComponentState();
}

const REFRESH_RATE = 60;
const _frameInterval =
    Duration(microseconds: Duration.microsecondsPerSecond ~/ REFRESH_RATE);
const maxframes = 100; // 120 帧足够了，对于 60和90 fps 来说
final lastFrames = ListQueue<FrameTiming>(maxframes);

double get fps {
  var lastFramesSet = <FrameTiming>[];
  for (FrameTiming timing in lastFrames) {
    if (lastFramesSet.isEmpty) {
      lastFramesSet.add(timing);
    } else {
      var lastStart =
          lastFramesSet.last.timestampInMicroseconds(FramePhase.buildStart);
      if (lastStart - timing.timestampInMicroseconds(FramePhase.rasterFinish) >
          (_frameInterval.inMicroseconds * 2)) {
        // in different set
        break;
      }
      lastFramesSet.add(timing);
    }
  }
  var framesCount = lastFramesSet.length;
  var costCount = lastFramesSet.map((t) {
    // 耗时超过 frameInterval 会导致丢帧
    // 下面这个公式，计算出理论帧数
    return ((t.totalSpan.inMicroseconds - t.vsyncOverhead.inMicroseconds) ~/
            _frameInterval.inMicroseconds) +
        1;
  }).fold(0, (a, b) => a + b);
  // fps ≈ REFRESH*RATE * 实际绘制帧数 / 理论绘制帧数
  // 解决停在30的问题。。。后期待优化
  // if (framesCount == 1 && costCount == 2) {
  //   return 60;
  // }
  return framesCount * REFRESH_RATE / costCount;
}

class _FpsTextComponentState extends State<FpsTextComponent> {
  int _fps = 0;

  int callbackLength = 0;
  int lastOneSpan = 0;

  void _onReportTimings(List<FrameTiming> timings) {
    print(timings.length);
    print(timings[0]);

    // 把 Queue 当作堆栈用
    for (FrameTiming timing in timings) {
      lastFrames.addFirst(timing);
    }

    // 只保留 maxframes
    while (lastFrames.length > maxframes) {
      lastFrames.removeLast();
    }

    int fpsTemp = fps.round();
    setState(() {
      callbackLength = timings.length;
      var timing = timings[0];
      lastOneSpan =
          timing.totalSpan.inMicroseconds - timing.vsyncOverhead.inMicroseconds;
      _fps = fpsTemp;
    });
  }

  @override
  void initState() {
    super.initState();
    WidgetsFlutterBinding.ensureInitialized().addTimingsCallback((timings) {
      // _onReportTimings(timings);

      var framesCount = timings.length;
      var costCount = timings.map((t) {
        // 耗时超过 frameInterval 会导致丢帧
        //ui或者是raster时间超过单个周期，才认为是丢帧，参考devTool的标准
        if (t.buildDuration.inMicroseconds >= _frameInterval.inMicroseconds ||
            t.rasterDuration.inMicroseconds >= _frameInterval.inMicroseconds) {
          return t.buildDuration.inMicroseconds ~/
                  _frameInterval.inMicroseconds +
              t.rasterDuration.inMicroseconds ~/ _frameInterval.inMicroseconds +
              1;
        } else {
          return 1;
        }
      }).fold(0, (a, b) => a + b);
      double fps = framesCount * 60 / costCount;
      setState(() {
        callbackLength = timings.length;
        _fps = fps.round();
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text("fps:$_fps"),
        Text("length:$callbackLength"),
        Text("ls:$lastOneSpan"),
      ],
    );
  }
}
